package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexFunc(context *gin.Context) {
	// 当在中间件或handler中启动新的goroutine时，不能使用原始的上下文（context *gin.Context），必须使用其只读副本（context.Copy()）。
	go aaaa(context.Copy())
	fmt.Println("index...")
	name, ok := context.Get("name") // 在这个中间件接收值，m2传过来的
	if ok {
		fmt.Println(name) // lalala
	}
	context.JSON(http.StatusOK, gin.H{
		"msg": "ok",
	})
}
func aaaa(context *gin.Context) {
	lalala, ok := context.Get("name") // 在这个中间件接收值m2传过来的，是indexFunc 调用时传过来的
	if ok {
		fmt.Println(lalala) // lalala
	}
}

// 写一个HandlerFunc作为中间件，参数是布尔值
func globalMiddleware(doCheck bool) gin.HandlerFunc {
	// 这里写一些比如连接数据库等操作的准备工作
	return func(context *gin.Context) {
		// 这里写具体逻辑
		if doCheck {
			fmt.Println("使用了全局中间件。。。")
		} else {
			context.Next()
		}
	}
}

func m2(context *gin.Context) {
	fmt.Println("m2 in ...")
	// 计时
	start := time.Now()
	//context.Next() // 调用后续处理函数，不会先执行下面的代码，会先执行其他中间件函数，其他的中间件函数执行完以后，才会继续执行下面的代码
	//context.Abort() // 阻止调用后续处理的中间件，直接接着往下执行,但是下面的本函数的其他代码可以执行完
	cost := time.Since(start)
	fmt.Println("耗时：", cost)
	fmt.Println("m2 out ...")
	context.Set("name", "lalala") // 中间件直接互相传值，传值给其他所有要执行的函数都可以接受到该参数
}

func main() {
	r := gin.Default()

	// 可以使用全局注册，如下写法：
	// 可以写入多个中间件注册进去的
	r.Use(m2, globalMiddleware(true)) // 可以注册多个中间件，写多个

	// 所有路由接口都已经使用了 m2 中间件
	r.GET("/shop", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "shop"})
	})
	r.GET("/user", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "user"})
	})

	r.GET("/index", indexFunc) // 这种写法也可以

	r.Run(":9090")
}
